package com.lsh.payment.core.service.mispurse.impl;

import com.alibaba.fastjson.JSON;
import com.lsh.payment.api.model.basevo.BaseResponse;
import com.lsh.payment.api.model.basevo.ExceptionStatus;
import com.lsh.payment.api.model.mispurse.MisPayContent;
import com.lsh.payment.api.model.mispurse.MisPayResponse;
import com.lsh.payment.api.model.payment.PaymentRequest;
import com.lsh.payment.core.constant.BusinessConstant;
import com.lsh.payment.core.exception.BusinessException;
import com.lsh.payment.core.model.payasync.ResultNotifyModel;
import com.lsh.payment.core.model.payenum.PayStatus;
import com.lsh.payment.core.model.payenum.TradeModule;
import com.lsh.payment.core.model.payment.PayDeal;
import com.lsh.payment.core.service.async.PayEventBus;
import com.lsh.payment.core.service.paylog.PayLogService;
import com.lsh.payment.core.service.payment.IPayChannelService;
import com.lsh.payment.core.service.payment.impl.PayBaseService;
import com.lsh.payment.core.service.payment.impl.PayDealService;
import com.lsh.payment.core.strategy.payment.PayStrategyContext;
import com.lsh.payment.core.strategy.vo.mispurse.MisPurseResponse;
import org.apache.commons.lang3.StringUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import javax.annotation.Resource;
import java.math.BigDecimal;
import java.util.Date;
import java.util.HashMap;
import java.util.Map;

/**
 * Project Name: lsh-payment
 *
 * @author miaozhuang
 * Date: 17/8/23
 * 北京链商电子商务有限公司
 * Package com.lsh.payment.core.service.xypay.impl
 * desc:
 */

@Service
public class PursePayServiceImpl implements IPayChannelService {

    private static Logger logger = LoggerFactory.getLogger(PursePayServiceImpl.class);

    @Autowired
    private PayBaseService payBaseService;

    @Autowired
    private PayDealService payDealService;

    @Autowired
    private PayLogService payLogService;

    @Resource
    private PayStrategyContext strategies;

    @Override
    public BaseResponse prepay(PaymentRequest paymentRequest) {

        paymentRequest.setTrade_module(TradeModule.ORDER.getName());
        MisPayResponse<MisPayContent> response = new MisPayResponse<>();

        String uid = paymentRequest.getUid();
        if(StringUtils.isBlank(uid)){
            throw new BusinessException(ExceptionStatus.E2001002.getCode(), ExceptionStatus.E2001002.getMessage() + " uid 不能为空");
        }

        PayDeal payDeal = builderPayDeal(paymentRequest);
        MisPayContent content = this.DealPayRequest(paymentRequest, payDeal);
        response.setContent(content);
        response.setRet(Integer.parseInt(ExceptionStatus.SUCCESS.getCode()));
        response.setMsg(ExceptionStatus.SUCCESS.getMessage());

        return response;
    }

    @Transactional(rollbackFor = Exception.class, readOnly = false)
    public PayDeal builderPayDeal(PaymentRequest paymentRequest) {
        //入库
        PayDeal payDeal = payBaseService.prePayment(paymentRequest);

        return payDeal;
    }

    /**
     * @param paymentRequest 请求参数
     * @return QfResponse     返回参数
     */
    public MisPayContent DealPayRequest(PaymentRequest paymentRequest, PayDeal payDeal) {
        MisPayContent respContent = new MisPayContent();

        respContent.setTrade_id(payDeal.getTradeId());
        //已经成功直接返回
        if (PayStatus.PAY_SUCCESS.getValue() == payDeal.getPayStatus()) {
            //已经支付成功
            return respContent;
        }

        //调用第三方进行支付
        MisPurseResponse misPurseResponse = this.requestMisChannel(payDeal, paymentRequest);
        respContent.setMisPurseResponse(JSON.toJSONString(misPurseResponse));

        if (StringUtils.isNotBlank(misPurseResponse.getTransactionId())) {
            PayDeal payDealNotify = payDealService.queryPayDealByPayPaymentNo(misPurseResponse.getOut_trade_no());
            if (null != payDealNotify) {
                payDealNotify.setChannelTransaction(misPurseResponse.getTransactionId());
//                MisPurseQueryModel misPurseQueryModel = new MisPurseQueryModel(payDealNotify);
                // 查询支付结果
                logger.info("通知 业务支付成功:" + JSON.toJSONString(payDealNotify));

                ResultNotifyModel resultNotifyModel = new ResultNotifyModel(payDealNotify);
                PayEventBus.post(resultNotifyModel);
            }
        }

        //记录操作日志
        payLogService.insertLog(payDeal.getPayId(), payDeal.getPayPaymentNo(), payDeal.getTradeId(), PayStatus.CREATE_PAYMENT.getValue(),
                BusinessConstant.OPERATE_SUCCESS, JSON.toJSONString(paymentRequest), JSON.toJSONString(respContent),paymentRequest.getVenderId());

        return respContent;
    }

    /**
     * 调用第三方进行支付
     *
     * @param payDeal        支付平台记录
     * @param paymentRequest 下单请求参数
     * @return 请求返回参数
     */
    private MisPurseResponse requestMisChannel(PayDeal payDeal, PaymentRequest paymentRequest) {
        PayDeal payDealUpd = new PayDeal();
        payDealUpd.setPayId(payDeal.getPayId());

        Map<String, String> misRequestMap = new HashMap<>(5);
        misRequestMap.put("payPaymentNo", payDeal.getPayPaymentNo());
        misRequestMap.put("payAmount", payDeal.getRequestAmount().toString());
        misRequestMap.put("channelType", paymentRequest.getTrade_type());
        misRequestMap.put("uid", paymentRequest.getUid());

        MisPurseResponse misPurseResponse = (MisPurseResponse) strategies.generatePayParams(BusinessConstant.MIS_PAY, misRequestMap);

        if (misPurseResponse == null || BusinessConstant.PAY_REQUEST_FAIL.equals(misPurseResponse.getCode())) {
            logger.error("调mis下单失败:" + payDeal.getPayId());
            throw new BusinessException(ExceptionStatus.E2001005.getCode(), ExceptionStatus.E2001005.getMessage() + ":" + misPurseResponse.getMsg());
        }

        logger.info("mis下单成功:" + payDeal.getPayId());
        //更新流水中的钱方订单号
        payDealUpd.setChannelTransaction(misPurseResponse.getTransactionId());
        payDealUpd.setPayStatus(PayStatus.PAY_SUCCESS.getValue());
        payDealUpd.setPayTime(new Date());
        payDealUpd.setDoneTime(new Date());
        payDealUpd.setReceiveAmount(new BigDecimal(misPurseResponse.getTrade_money()));
        //
        if (payDealService.updatePayDeal(payDealUpd) > 0) {
            //插入task
//            PayEventBus.post(new payTaskModel(payDeal));
            //返回参数处理
            return misPurseResponse;

        } else {
            logger.error("下单后,更新支付流水失败:" + payDeal.getPayPaymentNo());
            throw new BusinessException(ExceptionStatus.E2003001.getCode(), ExceptionStatus.E2003001.getMessage());
        }
    }
}

